package org.xserver.component.handler.ext;

import java.nio.charset.Charset;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xserver.component.core.XServerHttpContextAttachment;
import org.xserver.component.handler.ext.http.HttpResponseWriteHandler;
import org.xserver.component.handler.ext.websocket.WebsocketWriteHandler;

/**
 * This is abstract class for write response to client. The implement classes do
 * the real setContent and Channel write works.
 * 
 * <pre>
 *  XServer support some write handler, as follow:
 *  <ul>
 *  <li>{@link HttpResponseWriteHandler}, it response data to client by http</li>
 *  <li>{@link WebsocketWriteHandler}, it response data to client by websocket</li>
 *  <li>...</li>
 *  </ul>
 *  other type or other process need provided, can implements AbstractWriteHandler
 * </pre>
 * 
 * @author idoldefine
 * 
 */
public abstract class AbstractWriteHandler implements WriteHandler {
	public static final Charset DEFAULT_CONTENT_CHARSET = CharsetUtil.UTF_8;

	private static final Logger log = LoggerFactory
			.getLogger(AbstractWriteHandler.class);

	@Override
	public void writeResponse(XServerHttpContextAttachment attachment,
			Object obj) throws Exception {
		Channel channel = attachment.getChannelHandlerContext().getChannel();
		if (channel != null && channel.isConnected() && channel.isOpen()) {
			obj = getContent(attachment, obj);
			doWriteResponse(attachment, obj);
		} else {
			if (channel != null) {
				channel.close();
			}
			log.info("remote client[{}] close the connection.", attachment
					.getRequest().getRemoteAddress());
		}
	}

	protected void doWriteResponse(XServerHttpContextAttachment attachment,
			Object obj) throws Exception {
		ChannelFuture future = doWrite(attachment, obj);

		ChannelFutureListener listener = getListener(attachment, obj);

		if (listener != null) {
			future.addListener(listener);
		}
	}

	protected abstract Object getContent(
			XServerHttpContextAttachment attachment, Object obj)
			throws Exception;

	protected abstract ChannelFuture doWrite(
			XServerHttpContextAttachment attachment, Object obj);

	protected abstract ChannelFutureListener getListener(
			XServerHttpContextAttachment attachment, Object obj)
			throws Exception;
}
